﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Threading;
using System.Xml.Linq;

namespace Reticle
{
    public partial class Main : Form
    {
        public string tabParentKey { get; private set; }
        public Point location { get; private set; }
        public Dictionary<string, string> BotSettings { get; private set; }
        

        public Main()
        {
            InitializeComponent();
        }
   
        private void Window_Load(object sender, EventArgs e)
        {
            Thread news = new Thread(new ThreadStart(fetchNewsAndVersion));
            Thread plugins = new Thread(new ThreadStart(fetchPlugins));
            Thread server = new Thread(new ThreadStart(Manager.FetchServerXML));
            populateMenuProfiles("file");
            Profile profile = new Profile();
            profile.CreateProfile();
            BotSettings = Manager.LoadSettings();
            tabParentKey = tabControl.SelectedTab.Name;

            // create plugin menu on load
            CreatePluginMenu();

            // set the join/leave checkbox for the current profile
            SetJoinLeave(tabParentKey);

            // set the disable queue checkbox for the current profile
            SetDisableQueue(tabParentKey);

            // Fetch News and Version
            news.Start();

            // Load plugins
            plugins.Start();

            // Fetch infro.xml from server for verbytes, plugins, etc
            server.Start();
        }

        public void CreatePluginMenu()
        {
            foreach (Bot bot in Manager.Bots)
            {
                if (bot.BotKey == tabParentKey)
                {
                    bot.CreateMenu();
                }
            }
        }

        public void fetchPlugins()
        {
            //Thread.Sleep(1000);
            foreach (Bot bot in Manager.Bots)
            {
                bot.LoadPlugins();
            }
        }

        public void AddTab(TabPage tabPage)
        {
            tabControl.TabPages.Add(tabPage);
        }

        public void RemoveTab(string key)
        {
            tabControl.TabPages.RemoveByKey(key);
        }

        public bool CheckTab(string id)
        {
            foreach (TabPage tabPage in tabControl.TabPages)
            {
                if (tabPage.Text == id)
                {
                    return true;
                }
            }

            return false;
        }

        public string checkSetting(string setting)
        {
            Dictionary<string, string> botSet = BotSettings;

            switch (setting)
            {
                case "chatevent":
                    return botSet["chatevent"];
                case "urllinks":
                    return botSet["urllinks"];
                case "imagebot":
                    return botSet["imagebot"];
                case "youtubebot":
                    return botSet["youtubebot"];
                case "youtubeembed":
                    return botSet["youtubeembed"];
                case "imageembed":
                    return botSet["imageembed"];
                case "star-verbyte":
                    return botSet["star-verbyte"];
                case "w2bn-verbyte":
                    return botSet["w2bn-verbyte"];
                case "d2dv-verbyte":
                    return botSet["d2dv-verbyte"];
                case "war3-verbyte":
                    return botSet["war3-verbyte"];
                case "notifytalk":
                    return botSet["notifytalk"];
                case "notifyemote":
                    return botSet["notifyemote"];
                case "notifywhisper":
                    return botSet["notifywhisper"];
            }

            return null;
        }

        public void RefreshSettings()
        {
            BotSettings = Manager.LoadSettings();
        }

        public void InvokeScript(string botKey, string name, params object[] args)
        {
            if (tabControl.TabPages[botKey].Controls[0].InvokeRequired)
            {
                tabControl.TabPages[botKey].Controls[0].Invoke((MethodInvoker)delegate() { InvokeScript(botKey, name, args); });
            }
            else
            {
                WebBrowser browser = (WebBrowser)tabControl.TabPages[botKey].Controls[0];

                browser.Document.InvokeScript(name, args);
            }
        }

        public void TabIcon(int status, string tabKey)
        {
            try
            {
                if (tabControl.TabPages[tabKey].InvokeRequired)
                {
                    tabControl.Invoke((MethodInvoker)delegate() { TabIcon(status, tabKey); });
                }
                else
                {
                    tabControl.TabPages[tabKey].ImageIndex = status;
                }
            }
            catch (Exception) { }
        }

        public string CurrentTabKey()
        {
            if (tabControl.InvokeRequired)
            {
                return (string)tabControl.Invoke(
                  new Func<String>(() => CurrentTabKey())
                );
            }
            else
            {
                Manager.TabKey = (string)tabControl.SelectedTab.Name;
                return (string)tabControl.SelectedTab.Name;
            }
        }

        /*public void CurrentTabKey()
        {
            if (tabControl.InvokeRequired)
            {
                tabControl.Invoke((MethodInvoker)delegate() { CurrentTabKey(); });
            }
            else
            {
                Manager.TabKey = tabControl.SelectedTab.Name;
            }
        }*/

        public void AddPluginMenu(ToolStripMenuItem menu)
        {
            if (InvokeRequired)
            {
                Invoke((MethodInvoker)delegate() { AddPluginMenu(menu); });
            }
            else
            {
                if (menu == null)
                {
                    return;
                }
                menuStrip1.Items.RemoveByKey("menuPlugins");
                menuStrip1.Items.Insert(3, menu);
                //loadPluginsToolStripMenuItem.DropDownItems.Add(menu);
            }
        }

        public void Notify(string title, string text, string type)
        {
            bool sendNotify = false;

            if (InvokeRequired)
            {
                Invoke((MethodInvoker)delegate() { Notify(title, text, type); });
            }
            else
            {
                if (this.WindowState == FormWindowState.Minimized)
                {
                    switch (type)
                    {
                        case "talk":
                            if (checkSetting("notifytalk") == "1")
                            {
                                sendNotify = true;
                            }
                            break;
                        case "emote":
                            if (checkSetting("notifyemote") == "1")
                            {
                                sendNotify = true;
                            }
                            break;
                        case "whisper":
                            if (checkSetting("notifywhisper") == "1")
                            {
                                sendNotify = true;
                            }
                            break;
                    }

                    if (sendNotify)
                    {
                        TrayIcon.ShowBalloonTip(5000, title, text, ToolTipIcon.Info);
                    }
                }
            }
        }

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string botKey = tabControl.SelectedTab.Name;
            foreach (Bot bot in Manager.Bots)
            {
                if (botKey == bot.BotKey)
                {
                    //bot.Disconnect();
                    if (bot.IsConnected() == false)
                    {
                        // check to see if they have the needed hashes
                        if (bot.checkHashesBot(bot.client.Settings.Client))
                        {
                            bot.Connect();
                        }
                    }
                }
            }
        }

        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string botKey = tabControl.SelectedTab.Name;

            foreach (Bot bot in Manager.Bots)
            {
                if (botKey == bot.BotKey)
                {
                    bot.Disconnect();
                }
            }
        }

        public void fetchNewsAndVersion()
        {
          try
          {
              string version = Manager.CheckVersion();

              InvokeScript(tabParentKey, checkSetting("chatevent"), "<div id=\"chattext\"><span class=\"gray\">News: " + Helper.ConvertUrlsToLinks(Manager.FetchNews()) + "</span></div>");
              AddChat(tabParentKey, "<div id=\"chattext\"><span class=\"gray\">News: " + Helper.ConvertUrlsToLinks(Manager.FetchNews()) + "</span></div>");

              switch (version)
              {
                  case "error":
                      InvokeScript(tabParentKey, checkSetting("chatevent"), "<div id=\"chattext\"><span class=\"yellow\">There was a problem checking your version, the host server may be down.</span></div>");
                      AddChat(tabParentKey, "<div id=\"chattext\"><span class=\"yellow\">There was a problem checking your version, the host server may be down.</span></div>");
                      break;
                  case "current":
                      InvokeScript(tabParentKey, checkSetting("chatevent"), "<div id=\"chattext\"><span class=\"green\">You are running the latest version of Reticle.</span></div>");
                      AddChat(tabParentKey, "<div id=\"chattext\"><span class=\"green\">You are running the latest version of Reticle.</span></div>");
                      break;
                  case "outdated":
                      InvokeScript(tabParentKey, checkSetting("chatevent"), "<div id=\"chattext\"><span class=\"red\">Your bot is outdated, please check " + Helper.ConvertUrlsToLinks("http://www.bnetweb.org") + " for updates.</span></div>");
                      AddChat(tabParentKey, "<div id=\"chattext\"><span class=\"red\">Your bot is outdated, please check " + Helper.ConvertUrlsToLinks("http://www.bnetweb.org") + " for updates.</span></div>");
                      break;
              }
          }
          catch (Exception)
          {
            // log errors
          }
        }

        public void fetchVerbytes()
        {
            Manager.FetchVerbytes();
        }

        private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            WebBrowser browser = (WebBrowser)tabControl.TabPages[tabParentKey].Controls[0];
            browser.Document.InvokeScript("scrollBottom");

            string chathtml = "";
            string ophtml = "";
            string userhtml = "";

            foreach (Bot bot in Manager.Bots)
            {
                if (bot.BotKey == tabControl.SelectedTab.Name)
                {
                    foreach (string chat in bot.ChatHTML)
                    {
                        chathtml += chat;
                    }
                    foreach (string op in bot.OpHTML)
                    {
                        ophtml += op;
                    }
                    foreach (string user in bot.UserHTML)
                    {
                        userhtml += user;
                    }

                    if (bot.IsConnected())
                    {
                        browser.Document.GetElementById("channelname").InnerHtml = "" +
                                "<span class=\"yellow\">" + bot.CurrentChannel + "&nbsp;&nbsp;</span><span class=\"white\">(</span><span class=\"gray\">" + bot.ChannelUsers.ToString() + "</span><span class=\"white\">)</span>";
                    }
                    else
                    {
                        browser.Document.GetElementById("channelname").InnerHtml = "";
                    }

                    browser.Document.GetElementById("chattext").InnerHtml = chathtml;
                    browser.Document.GetElementById("channel").InnerHtml = "" +
                        "<table id=\"chantable\" cellspacing=\"0\" cellpadding=\"0\">" +
				        "<tbody id=\"operator\">" + ophtml + "</tbody>" +
				        "<tbody id=\"user\">" + userhtml + "</tbody>" +
			            "</table>";

                    if (bot.IsConnected())
                    {
                        TabIcon(0, tabControl.SelectedTab.Name);
                    }
                    else
                    {
                        TabIcon(1, tabControl.SelectedTab.Name);
                    }

                    // set the join/leave checkbox for the current profile
                    SetJoinLeave(bot.BotKey);

                    // set the disable queue checkbox for the current profile
                    SetDisableQueue(bot.BotKey);

                    // Create Plugin Menu for this profile
                    bot.CreateMenu();
                }
            }

            tabControl.TabPages[tabParentKey].Controls[0].Parent = tabControl.SelectedTab;
            tabParentKey = tabControl.SelectedTab.Name;
        }

        public void ClearChannel(string botKey)
        {
            if (tabControl.InvokeRequired)
            {
                tabControl.Invoke((MethodInvoker)delegate() { ClearChannel(botKey); });
            }
            else
            {
                WebBrowser browser = (WebBrowser)tabControl.TabPages[tabParentKey].Controls[0];

                foreach (Bot bot in Manager.Bots)
                {
                    if (bot.BotKey == botKey)
                    {
                        bot.OpHTML.Clear();
                        bot.UserHTML.Clear();
                        browser.Document.InvokeScript("clearChannel");
                    }
                }
            }
        }

        public void ChannelName(string botKey, string channel, int users)
        {
            if (tabControl.InvokeRequired)
            {
                tabControl.Invoke((MethodInvoker)delegate() { ChannelName(botKey, channel, users); });
            }
            else
            {
                WebBrowser browser = (WebBrowser)tabControl.TabPages[tabParentKey].Controls[0];

                foreach (Bot bot in Manager.Bots)
                {
                    if (bot.BotKey == botKey)
                    {
                        browser.Document.GetElementById("channelname").InnerHtml = "" +
                            "<span class=\"yellow\">" + channel + "&nbsp;&nbsp;</span><span class=\"white\">(</span><span class=\"gray\">" + users.ToString() + "</span><span class=\"white\">)</span>";
                    }
                }
            }
        }

        public void AddChat(string botKey, string chat)
        {
            foreach (Bot bot in Manager.Bots)
            {
                if (botKey == bot.BotKey)
                {
                    bot.ChatHTML.Add(chat);
                    if (bot.ChatHTML.Count > 255)
                    {
                        bot.ChatHTML.RemoveRange(0, 1);
                    }
                }
            }
        }

        public void AddUser(int botID, string user, string type)
        {
            foreach (Bot bot in Manager.Bots)
            {
                if (botID == bot.ID)
                {
                    if (type == "opfirst")
                    {
                        //bot.OpHTML.Add(user);
                        //Insert at position 0 so operators may be in order
                        bot.OpHTML.Insert(0, user);
                    }
                    else if (type == "op")
                    {
                        bot.OpHTML.Add(user);
                    }
                    else if (type == "user")
                    {
                        bot.UserHTML.Add(user);
                    }
                }
            }
        }

        private void Main_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.ShowInTaskbar = false;
                this.Hide();
                TrayIcon.Visible = true;
            }
        }

        private void TrayIcon_MouseClick(object sender, MouseEventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
            this.ShowInTaskbar = true;
            TrayIcon.Visible = false;
        }

        private void txtSend_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                foreach (Bot bot in Manager.Bots)
                {
                    if (bot.BotKey == tabControl.SelectedTab.Name)
                    {
                        e.SuppressKeyPress = true;

                        if (txtSend.Text == "/cq" || txtSend.Text == "/scq")
                        {
                            Commands.ProcessCommand(txtSend.Text, bot);
                        }
                        else
                        {
                            bot.Enqueue(txtSend.Text);
                        }

                        txtSend.Clear();
                        txtSend.Focus();
                    }
                }
            }
            // doesn't catch Ctrl+v all the time?
            else if (e.KeyCode == Keys.V && e.Modifiers == Keys.Control)
            {
                foreach (Bot bot in Manager.Bots)
                {
                    if (bot.BotKey == tabControl.SelectedTab.Name)
                    {
                        e.SuppressKeyPress = true;

                        // get data from the clipboard to paste
                        string[] messages = Clipboard.GetText(TextDataFormat.Text).Split(new char[] { '\n' });

                        // if they are pasting only 1 line, don't send.
                        if (messages.Length > 1)
                        {
                            if (bot.DisableQueue == false)
                            {
                                for (int i = 0; i <= messages.Length - 1; i++)
                                {
                                    bot.Enqueue(messages[i]);
                                }
                            }
                            else
                            {
                                MessageBox.Show("ReEnable the Queue to paste messages.", "Queue Disabled");
                            }
                        }

                        txtSend.Clear();
                        txtSend.Focus();
                    }
                }
            }
        }

        private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                e.Handled = true;
            }
        }

        public void populateMenuProfiles(string type)
        {
            loadProfile.DropDownItems.Clear();
            //Dictionary<string, int> profiles = new Dictionary<string, int>();
            foreach (KeyValuePair<string, string> pair in Profile.GetProfiles(type))
            {
                //loadProfile.DropDownItems.Add(profile);
                ToolStripMenuItem it = (ToolStripMenuItem)loadProfile.DropDownItems.Add(pair.Key);
                it.Name = pair.Key;

                if (pair.Value == "1")
                {
                    it.Checked = true;
                }
                it.CheckOnClick = true;
            }
        }

        private void loadProfile_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            /*if (CheckTab(e.ClickedItem.Text))
            {
                Profile.CreateSingleProfile(e.ClickedItem.Text);
            }
            else
            {
                MessageBox.Show("Profile is already loaded.", "Profile");
            }*/

            ToolStripMenuItem it = (ToolStripMenuItem)loadProfile.DropDownItems[e.ClickedItem.Name];
            if (it.Checked)
            {
                for (int i = 0; i < tabControl.TabCount; i++)
                {
                    if (tabControl.TabCount <= 1)
                    {
                        MessageBox.Show("You cannot remove all profiles.", "Dumbass");
                        break;
                    }

                    foreach (Bot bot in Manager.Bots)
                    {
                        if (tabControl.SelectedTab.Name == bot.BotKey && tabControl.SelectedIndex != 0)
                        {
                            tabControl.SelectedIndex = 0;
                        }
                        else if (tabControl.SelectedTab.Name == bot.BotKey && tabControl.SelectedIndex == 0)
                        {
                            tabControl.SelectedIndex = 1;
                        }

                        if (bot.BotKey == it.Name)
                        {
                            bot.Disconnect();
                            // remove the tabpage
                            Profile.UnloadProfile(bot.BotKey);
                            break;
                        }
                    }
                }
            }
            else
            {
                Profile.CreateSingleProfile(it.Name);
            }

        }

        private void tabControl_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                // iterate through all the tab pages
                for (int i = 0; i < tabControl.TabCount; i++)
                {
                    // get their rectangle area and check if it contains the mouse cursor
                    Rectangle r = tabControl.GetTabRect(i);
                    if (r.Contains(e.Location))
                    {
                        location = e.Location;
                        // show the context menu here
                        this.contextMenuStrip1.Show(this.tabControl, e.Location);
                    }
                }
            }
        }

        private void unloadProfile_Click(object sender, EventArgs e)
        {
            // iterate through all the tab pages
            for (int i = 0; i < tabControl.TabCount; i++)
            {
                if (tabControl.TabCount <= 1)
                {
                    MessageBox.Show("You cannot remove all profiles.", "Dumbass");
                    break;
                }

                foreach (Bot bot in Manager.Bots)
                {
                    if (tabControl.SelectedTab.Name == bot.BotKey && tabControl.SelectedIndex != 0)
                    {
                        tabControl.SelectedIndex = 0;
                    }
                    else if (tabControl.SelectedTab.Name == bot.BotKey && tabControl.SelectedIndex == 0)
                    {
                        tabControl.SelectedIndex = 1;
                    }

                    Rectangle r = tabControl.GetTabRect(i);
                    if (r.Contains(location))
                    {
                        if (bot.BotKey == tabControl.TabPages[i].Name)
                        {
                            bot.Disconnect();
                            // remove the tabpage
                            Profile.UnloadProfile(bot.BotKey);
                            break;
                        }
                    }
                }
                
            }

            populateMenuProfiles("bot");
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            About about = new About();
            about.Show();
        }

        private void visitBnetWebToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.bnetweb.org");
        }

        private void globalSettingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GlobalSettings settings = new GlobalSettings();
            settings.ShowDialog();
            //settings.Show();
        }

        private void SetJoinLeave(string botKey)
        {
            foreach (Bot bot in Manager.Bots)
            {
                if (botKey == bot.BotKey)
                {
                    if (bot.ShowJoinLeave)
                    {
                        showJoinLeaveNotificationsToolStripMenuItem.Checked = true;
                    }
                    else
                    {
                        showJoinLeaveNotificationsToolStripMenuItem.Checked = false;
                    }
                }
            }
        }

        private void showJoinLeaveNotificationsToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            foreach (Bot bot in Manager.Bots)
            {
                if (tabControl.SelectedTab.Name == bot.BotKey)
                {
                    if (showJoinLeaveNotificationsToolStripMenuItem.Checked)
                    {
                        bot.ShowJoinLeave = true;
                        Manager.SaveProfileSettings(bot.BotKey);
                    }
                    else
                    {
                        bot.ShowJoinLeave = false;
                        Manager.SaveProfileSettings(bot.BotKey);
                    }
                }
            }
        }

        private void SetDisableQueue(string botKey)
        {
            foreach (Bot bot in Manager.Bots)
            {
                if (botKey == bot.BotKey)
                {
                    if (bot.DisableQueue)
                    {
                        disableQueueToolStripMenuItem.Checked = true;
                    }
                    else
                    {
                        disableQueueToolStripMenuItem.Checked = false;
                    }
                }
            }
        }

        private void disableQueueToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            foreach (Bot bot in Manager.Bots)
            {
                if (tabControl.SelectedTab.Name == bot.BotKey)
                {
                    if (disableQueueToolStripMenuItem.Checked)
                    {
                        bot.DisableQueue = true;
                        Manager.SaveProfileSettings(bot.BotKey);

                        //bot.HandleChat(String.Format("<div id=\"chattext\"><span id=\"timestamp\">{0}</span><span class=\"red\">Queue disabled.</span></div>", Helper.TimeStamp()));
                    }
                    else
                    {
                        bot.DisableQueue = false;
                        Manager.SaveProfileSettings(bot.BotKey);

                        //bot.HandleChat(String.Format("<div id=\"chattext\"><span id=\"timestamp\">{0}</span><span class=\"green\">Queue enabled.</span></div>", Helper.TimeStamp()));
                    }
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void fetchNewsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Thread news = new Thread(new ThreadStart(fetchNewsAndVersion));
            news.Start();
        }

        private void checkVerbytesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Thread verbytes = new Thread(new ThreadStart(fetchVerbytes));
            verbytes.Start();
        }

        private void configToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GlobalSettings settings = new GlobalSettings(Program.Window.CurrentTabKey());
            settings.ShowDialog();
        }
    }
}
